//
//  SQLHandler.h
//  SQL演练
//
//  Created by Guo Rui on 2017/10/28.
//  Copyright © 2017年 GR Harry. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "SQLChain.h"
#import <FMResultSet.h>

@class SQLHandler, SQLChain, SQLHandleResult, FMDatabaseQueue;

typedef void (^SQLHandlerBlock)(SQLHandler *SQL);
typedef void (^SQLHandlerTransactionBlock)(SQLHandler *SQL, BOOL *rollback);
typedef void (^SQLHandlerResultParamBlock)(SQLHandleResult *result);
typedef SQLHandleResult *(^SQLHandlerArrayParamBlock)(NSArray *arguments);

@interface SQLHandler : NSObject

@property (strong, nonatomic, readonly) FMDatabaseQueue *dbQueue;

+ (instancetype)sharedInstance;

/**
 如果有数据库文件就连接数据库，如果没有数据库文件就创建。

 @param name 数据库的名称
 */
- (void)databaseWithName:(NSString *)name;


/**
 拼接SQL语句，并执行。方法为线程安全

 @param handle 拼接SQL语句的操作并且执行。
 @note  在handle中执行的多语句中，如果有查询语句，那么是没有结果集返回的。多语句插入时，不能插入data数据。
 */
+ (void)makeSafelyHandleSQL:(SQLHandlerBlock)handle;


/**
 拼接SQL语句，并执行。方法为线程安全,并且带有事务。* rollback = YES, 可以直接回滚。
 
 @param handle 拼接SQL语句的操作并且执行。
 @note  在handle中执行的多语句中，如果有查询语句，那么是没有结果集返回的。多语句插入时，不能插入data数据。批量执行时已经有事务保护，此时rollback,不会起作用.只对于单语句执行时，rollback才有效果。
 */
+ (void)makeTransactionHandleSQL:(SQLHandlerTransactionBlock)handle;

/**
 用于非绑定语句的执行， 支持语句的批量执行

 @return 如果执行的是查询语句，result.value 有值是FMResultSet。
 */
- (SQLHandleResult *)excute;


/**
 用于绑定语句的执行， 不支持语句的批量执行
 @param array : 待绑定的参数。
 @return 如果执行的是查询语句，result.value 有值是FMResultSet。
 */
- (SQLHandlerArrayParamBlock)excuteWithArgumentsInArray;


/**
 SQL 语句生成器
 */
@property (strong, nonatomic, readonly) SQLChain *generate;
@end


typedef enum : NSUInteger {
    SQLHandleTypeUpdate = 1,
    SQLHandleTypeQuery,
    SQLHandleTypeBatch
} SQLHandleType;

typedef void(^SQLHandleResultSetParamBlock)(FMResultSet *set);
typedef SQLHandleResult *(^SQLHandleResultNestSetBlockBlock)(SQLHandleResultSetParamBlock);
typedef SQLHandleResult *(^SQLHandleResultNoParamBlock)(void);

@interface SQLHandleResult: NSObject

+ (instancetype)resultWithValue:(FMResultSet *)value success:(BOOL)success handleType:(SQLHandleType)handleType;

/**
 *  如果 handleType == SQLHandleTypeUpdate, value 是 @(YES) or @(NO), 表示执行成功或失败.
 *  如果 handleType == SQLHandleTypeQuery, value 是 FMResultSet, 是查询的结果.
 */
@property (assign, nonatomic, readonly, getter=isSuccess) BOOL success;
@property (strong, nonatomic, readonly) FMResultSet *value;
@property (assign, nonatomic, readonly) SQLHandleType handleType;

/**
 将 value 中的值遍历出来

 @return 嵌套 block
 */
- (SQLHandleResultNestSetBlockBlock)enumerateSet;

@end
